package pkg4funlex;

import pkg4fungeneric.Code;

/**
 *
 * @author 4FunTeam
 */

public class Automaton {
//    private static int[] code = Analyzer.init();
//    private static Token atual;
//    private static Automato current_automata;
    int state;
    String lex;
    
    public Automaton() {
        state = 0;
        lex = "";
        //System.out.println("================== super constru");
    }

    public boolean transition(char c) {
        //System.out.println("================= super transition");
        return true;
    }
}

class QuoteAutomaton extends Automaton {
    public QuoteAutomaton() {
        super();
    }

    public boolean transition(char c) {
        switch(state) {
            case 0:
                state = 1;
                break;
            case 1:
                if(c == '"') return accept(lex+c);
                else if(c == '\n') Analyzer.printError("No closing double quote");
        }
        lex += c;
        return false;
    }

    private boolean accept(String s) {
        Analyzer.setToken(new Token("token_LitString", s));
        return true;
    }
}

class LogicAutomaton extends Automaton {
    public LogicAutomaton() {
        super();
    }

    public boolean transition(char c) {
        switch(state) {
            case 0:
                state = 1;
                break;
            case 1:
                if(c == '.') return isReserved(lex+c);
                else if(c == '\n') Analyzer.printError("No closing point");
        }
        lex += c;
        return false;
    }

    private boolean isReserved(String s) {
        if(Reserved.contains(s)) {
            Analyzer.setToken(new Token(Reserved.type(s), s));
            return true;
        }
        else Analyzer.printError("Invalid logic word");
        return false;
    }
}

class NumberAutomaton extends Automaton {
    String type;
    public NumberAutomaton(String signal) {
        state = 0;
        lex += signal;
        type = "token_LitInteger";
    }

    public boolean transition(char c) {
        switch(state) {
            case 0:
                if(Analyzer.code[c] == Code.DIGIT) break;
                if(c == '.'){
                    state = 1;
                    return false;
                }
                else if(c == 'E') {
                    state = 6;
                    return false; // falta ver se pós E tem digito
                }
                else return accept();
                //break;
            case 6: // N+E
                if(Analyzer.code[c] == Code.DIGIT) {
                    lex += 'E';
                    state = 7;
                    break;
                }
                else return accept();
            case 7: // N+EN+
                if(Analyzer.code[c] == Code.DIGIT) break;
                else return accept();
            case 1: // N+.
                if(Analyzer.code[c] != Code.DIGIT) return accept();
                lex += '.';
                type = "token_LitReal";
                state = 2;
                break;
            case 2: // é num real N+.N+
                if(Analyzer.code[c] == Code.DIGIT) break;
                else if(c == 'E') { 
                    state = 3;
                    return false; // Não coloca o E pois ainda não sabe-se se
                }                 // depois do E tem -?DIGITO
                else return accept();
            case 3: // N+.N+E
                if(Analyzer.code[c] == Code.DIGIT) {
                    lex += 'E';
                    state = 5;
                    break;
                }
                else if(Analyzer.code[c] == Code.MINUS) {
                    state = 4;
                    return false;// Não coloca o - ainda pois ainda não sabe-se
                                 //  se depois do - tem DIGITO
                }
                else return accept();
            case 4: // N+.?N+E-
                if(Analyzer.code[c] == Code.DIGIT) {
                    lex += "E-";
                    state = 5;
                    break;
                }
                else return accept();
            case 5: // N+.?N+E-N | // N+.?N+EN
                if(Analyzer.code[c] == Code.DIGIT) break;
                return accept();
        }
        lex += c;
        return false;
    }

    private boolean accept() {

       Analyzer.setToken(new Token(type, lex));

        return true;
        }
}

class RelOpAutomaton extends Automaton {
    private String id;
    public RelOpAutomaton() {
        super();
        id = "token_OpRel";
    }

    public boolean transition(char c) {
        switch(state) {
            case 0:
                if(c == '=') state = 1;
                else if(c == '<') state = 2;
                else if(c == '>' ) state = 3;
                lex += c;
                break;
            case 1:
                if(c == '=') {
                    lex += c;
                } else {
                    id = "=";
                }
                return accept();
            case 2: // anterior = '<'
                if(c == '=' || c == '>') {
                    lex += c;
                }
                return accept();
            case 3: // anterior = '>'
                if(c == '=') {
                    lex += c;
                }
                return accept();
        }
        return false;
    }

    private boolean accept() {
        Analyzer.setToken(createToken(lex));
        return true;
    }

    private Token createToken(String lexeme) {
        return new Token(id, lexeme);
    }
}

class WsAutomaton extends Automaton {
    private int count = 0;

    public WsAutomaton() {
        super();
    }

    public boolean transition(char c) {
        switch(state) {
            case 0: if (Analyzer.code[c] == Code.WS) {
                        state = 0;
                        count++;
                    }
                    else return accept();
                    break;
        }
        return false;
    }

    private boolean accept() {
        Analyzer.setCurrent_state(0);
        Scanner.setPos(count);
        return false;
    }
}

class IdAutomaton extends Automaton {
    public IdAutomaton() {
        super();
    }

    public boolean transition(char c) {
        switch(state) {
            case 0: state = 1;
                    break;
            case 1: if(Analyzer.code[c] == Code.LETTER) state = 1;
                    else if(Analyzer.code[c] == Code.DIGIT ) state = 1;
                    else return accept();
        }
        lex += String.valueOf(c);
        return false;
    }

    private boolean accept() {
        Analyzer.setToken(this.createToken(lex));
        return true;
    }
    
    private Token createToken(String lexeme) {
        String id;
        if(Reserved.contains(lexeme)) {
            id = Reserved.type(lexeme);
        }
        else id = "id";
        return new Token(id, lexeme);
    }
}


//            public int transition(char c) {
//                switch(code[c]) {
//                    case LETTER:
//                        current_state = 1;
//                        lex += c;
//                        break;
//                    case DIGIT: current_state = 1;
//                        lex += c;
//                        break;
//                    default:
//                        atual = makeToken(lex,"id");
//                        return lex.length();
//                }
//                return 0;
//            }
